moddbfandomcom-20200213-history
Haskell:Tutorials:Basics
Haskell Basics Before it All For starters: I expect you to know an imperative language, preferably C/C++, but not to have any idea about Haskell. But I expect you to have an interest in working with it, of course. The Idea The idea of Haskell is a mathematical one: Every programme is actually a mathematical function, from one set to another (Don't worry, I'll spare you the higher mathematics). Unlike imperative languages like C/C++, Haskell works with lazy evaluation, meaning it calculates variables and function the moment needed, not the moment mentioned. Thus, the following expressions are equal in Haskell: x = 3 print x print x x = 3 Well, in theory that is. In normal Haskell, it's not correct syntax, but we'll get to that soon enough. Haskell is also based on Lambda-Calculus, another idea C programmers will find funny. It's defining functions on-the-fly. Very good for loops, since Haskell does not have for or while. Running Haskell Either you use the Hugs Interpreter or the Glasgow Haskell Compiler for running Haskell scripts. The GHC can also compile and link the script to a binary, which is why I recommend it if you plan to do some serious game programming with it. GHC is also the only Haskell interpreter that I made to work with the HOpenGL extension. Hugs is pretty well known and sophisticated, but a pure interpreter. GHC compiles, but has also an interactive interpreter named GHCi. To run your Haskell scripts, use $> runhugs file.hs # For Hugs $> runhaskell file.hs # For GHC Alternatively you can also run the interactive mode which I recommend for debugging and learning. Under Linux, you can start them with $> hugs file.hs $> ghci file.hs In Windows, they both have semi-graphical front-ends you can find the Start-menus. In my examples, I will use the GHC/GHCi interpreter. There shouldn't be any difference, except for the OpenGL support. Hello World Since it's normal to make a "Hello World"-example, I will make one too. Plus it's very nice to show the versatility of this language. The simplest way to put a Hello World! on the screen is in interactive mode. Just put Prelude> "Hello, World!" "Hello, World!" Well, bummer, I hear you say. That's not magic. How can I feel superior, when it's as easy as HTML? Let's try something else: Prelude> print "Hello, World!" "Hello, World!" Prelude> putStrLn "Hello, World!" Hello, World! So we reached the level of Perl. Noticed the difference between print and putStrLn? print is a general purpose printing function. It can deal with strings as well as numbers, but as you see, it just throws the data out as they come in. putStrLn works with strings only, but it leaves the quotation marks, as you see. So, this only works in the interactive interpreter. For a distribution, we need to specify source code. Here the code, I will explain it right afterwards: -- hello.hs: Hello World Example main :: IO () main = do putStrLn "Hello, World!" As in C/C++, the entry function is called main. Nothing new so far. The line main :: IO () is the declaration of the function main. Actually, it is not necessary, as the compiler would find the type out for us if we didn't specify it. But since I like clean definitions (I am a bit of a mathematician), I add it. '::' is the definition sign, and IO () is a special type. It tells Haskell that main won't exactly evaluate a function, but doing some input and output (hence IO). main = do A Haskell function is actually a variable with a value. Before the '=', we specify the variable name, after it the value, or, because it is a function, a rule or arithmetic term to evaluate. But, I hear you yell, printing a string is not a value, is it? As much as the developers of Haskell would love to make it a value, it's not. So, we use the keyword 'do' here. 'do' tells Haskell, this function contains of imperative orders. Just like C/C++? Not quite. But that difference I will explain later. putStrLn "Hello, World!" And there is the command we use to print the string, as before. You can run it now, with $> runhaskell hello.hs or $> ghci hello.hs GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. Prelude> main Hello, World! So this is your Hello World example. Take a break before we move on. By the way, there's another Hello World, that's also correct and working, but I don't like it as much. main = putStrLn "Hello, World!" Why? As I said it, printing a string is not a value. Or is it? Going Further Hello World is pretty nice to see the essence of a language, but Haskell is made of functions, isn't it? Yes it is. Before I conclude the first tutorial, I want to show you how functions are used. If you know C++, you will surely understand this code: #include int main() { int n = 0; cout << "N = "; cin >> n; cout << "\nN*N = " << (n*n) << '\n'; return 0; } It maybe not the most useful application out there, but a nice example of I/O, which is the basic principle a computer works: Input, calculating, output. Ever since Turings first ideas, that's been the computer's way of life. So let me show you the same application in Haskell: square :: Int -> Int square n = n * n getNumber :: IO Int getNumber = do putStr "N = " readLn main :: IO () main = do n <- getNumber print (square n) Three functions for the same? Well, yes. But that doesn't have to be a disadvantage. It's Haskell's idea of re-usability, like objects in C++ or Java. Plus, Haskell deals with functions differently than other languages, so it's okay to define a bit more of them. (To be honest, square is not necessary, but it's an example after all.) The square function obviously takes an integer and returns an integer. It shouldn't be much of a deal to understand this function, but you can easily see how the usual kind of function is defined, the kind you know from school, like f(x) = x^2 . If you had some higher maths on college, you will also understand the following: f: \mathbb{Z} \rightarrow \mathbb{Z}, f(x) := x^2 That's what Haskell tries to be: Maths. Got it? getNumber is another IO-type function. It returns an integer. To explain it mathematically is a bit difficult, as maths don't care much about where it gets it's data from. You just take a pen and put them down. But if you had some Pascal in an earlier live, the called functions look a bit familiar to you. Actually, the only line of interest may be n <- getNumber As clear as this expression may be, as weird it looks to the imperative programmer. It means: Shove the result of getNumber into n''. Since '''getNumber' is not a mathematical function, but an IO one, we have to use the '<-' to get the returned value. Evaluation wouldn't work. Conclusion This concludes the first part of my Haskell tutorial. Next will be more on functions and the mysterious currying. If you have problems or questions, mail me at dusklykan at yahoo.co.uk. Thanks for listening.